package payload

// ErrorPayload is an error and redis.Payload
type ErrorPayload interface {
	Error() string
	Bytes() []byte
}

// IsErrorPayload returns if the given payload is a valid error payload.
func IsErrorPayload(payload Payload) bool {
	return payload.Bytes()[0] == '-'
}

// StandardErrPayload represents server error
type StandardErrPayload struct {
	Status string
}

func NewErrPayload(status string) *StandardErrPayload {
	return &StandardErrPayload{
		Status: status,
	}
}

func (r *StandardErrPayload) Bytes() []byte {
	return []byte("-" + r.Status + CRLF)
}

func (r *StandardErrPayload) Error() string {
	return r.Status
}

// UnknownErrPayload represents UnknownErr
type UnknownErrPayload struct{}

func NewUnknownErrPayload() *UnknownErrPayload {
	return &UnknownErrPayload{}
}

var unknownErrBytes = []byte("-Err unknown\r\n")

func (r *UnknownErrPayload) Bytes() []byte {
	return unknownErrBytes
}

func (r *UnknownErrPayload) Error() string {
	return "Err unknown"
}

// ArgNumErrPayload represents wrong number of arguments for command
type ArgNumErrPayload struct {
	Cmd string
}

func NewArgNumErrPayload(cmd string) *ArgNumErrPayload {
	return &ArgNumErrPayload{Cmd: cmd}
}

func (r *ArgNumErrPayload) Bytes() []byte {
	return []byte("-ERR wrong number of arguments for '" + r.Cmd + "' command\r\n")
}

func (r *ArgNumErrPayload) Error() string {
	return "ERR wrong number of arguments for '" + r.Cmd + "' command"
}

// SyntaxErrPayload represents meeting unexpected arguments
type SyntaxErrPayload struct{}

var syntaxErrBytes = []byte("-Err syntax error\r\n")

func NewSyntaxErrPayload() *SyntaxErrPayload {
	return &SyntaxErrPayload{}
}

// Bytes marshals redis.Payload
func (r *SyntaxErrPayload) Bytes() []byte {
	return syntaxErrBytes
}

func (r *SyntaxErrPayload) Error() string {
	return "Err syntax error"
}

// WrongTypeErrPayload represents operation against a key holding the wrong kind of value
type WrongTypeErrPayload struct{}

func NewWrongTypeErrPayload() *WrongTypeErrPayload {
	return &WrongTypeErrPayload{}
}

var wrongTypeErrBytes = []byte("-WRONGTYPE Operation against a key holding the wrong kind of value\r\n")

func (r *WrongTypeErrPayload) Bytes() []byte {
	return wrongTypeErrBytes
}

func (r *WrongTypeErrPayload) Error() string {
	return "WRONGTYPE Operation against a key holding the wrong kind of value"
}

// ProtocolErrPayload represents meeting unexpected byte during parse requests
type ProtocolErrPayload struct {
	Msg string
}

func NewProtocolErrPayload(msg string) *ProtocolErrPayload {
	return &ProtocolErrPayload{Msg: msg}
}

// Bytes marshals redis.Payload
func (r *ProtocolErrPayload) Bytes() []byte {
	return []byte("-ERR Protocol error: '" + r.Msg + "'\r\n")
}

func (r *ProtocolErrPayload) Error() string {
	return "ERR Protocol error: '" + r.Msg
}
